package packetCap.CapPacket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;

import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import packetCap.UI.TableSorter;
import jpcap.JpcapCaptor;
import jpcap.NetworkInterface;
import jpcap.PacketReceiver;
import jpcap.packet.ARPPacket;
import jpcap.packet.ICMPPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;
import jpcap.packet.TCPPacket;
import jpcap.packet.UDPPacket;

public class myCaptor {
    private JpcapCaptor jpcap = null;
    private packSeq packetSeq;//包序号
    private NetworkInterface[] devices;
    private boolean startFlag = false;
    private String targetDeviceName = null;
    private String[] wantedProtocal = null;
    private JTable tab;
    Map<String, ArrayList<myPacket>> packetMap;

    public myCaptor(Map<String, ArrayList<myPacket>> map) {
        devices = JpcapCaptor.getDeviceList();
        packetSeq = new packSeq();
        packetMap = map;
    }

    public void initCaptor() {
        if (targetDeviceName != null) {
            for (NetworkInterface ni : devices) {
                if (ni.name.equals(targetDeviceName)) {
                    try {
                        jpcap = JpcapCaptor.openDevice(ni, 65535, true, 50);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void begin() {
        if (jpcap != null) {
            while (startFlag) {
                jpcap.processPacket(4, new Receiver(tab, packetSeq, wantedProtocal, packetMap));
            }
        }
    }

    public NetworkInterface[] getDevices() {
        return devices;
    }

    public boolean isStartFlag() {
        return startFlag;
    }

    public void setStartFlag(boolean startFlag) {
        this.startFlag = startFlag;
    }

    public void setTargetDeviceName(String targetDeviceName) {
        this.targetDeviceName = targetDeviceName;
    }

    public JTable getTab() {
        return tab;
    }

    public void setTab(JTable tab) {
        this.tab = tab;
    }

    public String[] getWantedProtocal() {
        return wantedProtocal;
    }

    public void setWantedProtocal(String[] wantedProtocal) {
        this.wantedProtocal = wantedProtocal;
    }

    public Map<String, ArrayList<myPacket>> getPacketMap() {
        return packetMap;
    }

    public void setPacketMap(Map<String, ArrayList<myPacket>> packetMap) {
        this.packetMap = packetMap;
    }

}

class packSeq {
    private int num;

    public packSeq() {
        num = 0;
    }

    public void inc() {
        num++;
    }

    public void dec() {
        num--;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

}

class Receiver implements PacketReceiver {
    JTable tab;
    packSeq num;
    int len;
    String protocal;
    String dst_ip;
    String src_ip;
    String[] wantedProtocal;
    ArrayList<String> tempList;
    volatile DefaultTableModel temp;
    Map<String, ArrayList<myPacket>> packetMap;

    public Receiver(JTable uiTab, packSeq packSeq, String[] wantedProto, Map<String, ArrayList<myPacket>> map) {
        tab = uiTab;
        num = packSeq;
        wantedProtocal = wantedProto;
        temp = (DefaultTableModel) uiTab.getModel();
//		temp = (DefaultTableModel)(((TableSorter)uiTab.getModel()).getTableModel());
        packetMap = map;
    }

    @Override
    public void receivePacket(Packet p) {

        protocal = "default";
        dst_ip = "default:0.0.0.0";
        src_ip = "default:0.0.0.0";
        tempList = new ArrayList<String>();
        String trueProtocal = null;
        if (p instanceof IPPacket && ((IPPacket) p).version == 4) {
            if (wantedProtocal[0].equals("") && wantedProtocal[2].equals("") && wantedProtocal[3].equals("") && wantedProtocal[4].equals("")) {
                return;
            }
            num.inc();
            IPPacket ip = (IPPacket) p;
            switch (ip.protocol) {
                case 1:
                    if (wantedProtocal[2].equals("")) {
                        return;
                    }
                    protocal = "ICMP";
                    trueProtocal = protocal;
                    len = ((ICMPPacket) ip).len;
                    break;

                case 6:
                    if (wantedProtocal[3].equals("")) {
                        return;
                    }
                    protocal = "TCP";
                    trueProtocal = protocal;
                    len = ((TCPPacket) ip).len;
                    String data_tcp = new String(((TCPPacket) ip).data);
                    if (data_tcp.indexOf("HTTP") != -1) {
                        protocal = "HTTP";
                    }
                    break;
                case 17:
                    if (wantedProtocal[4].equals("")) {
                        return;
                    }
                    protocal = "UDP";
                    trueProtocal = protocal;
                    len = ((UDPPacket) ip).len;
                    String data = new String(((UDPPacket) ip).data);
                    if (data.indexOf("M-SEARCH") != -1 || data.indexOf("NTS: ssdp:alive") != -1 || data.indexOf("NTS: ssdp:byebye") != -1) {
                        protocal = "SSDP";
                    }
                    break;
                default:
//				protocal = "IP";
//				len = ip.len;
                    return;
            }

            dst_ip = ip.dst_ip.toString();
            src_ip = ip.src_ip.toString();
            tempList.add(num.getNum() + "");
            tempList.add(protocal);
            tempList.add(src_ip);
            tempList.add(dst_ip);
            tempList.add(len + "");

        } else if (p instanceof ARPPacket) {
            if (wantedProtocal[1].equals("")) {
                return;
            }
            num.inc();
            ARPPacket arp = (ARPPacket) p;
            protocal = "ARP";
            trueProtocal = protocal;
            len = arp.len;
            tempList.add(num.getNum() + "");
            tempList.add(protocal);
            tempList.add(src_ip);
            tempList.add(dst_ip);
            tempList.add(len + "");

        } else {
            return;
        }
        temp.addRow(tempList.toArray());
//		tab.setModel(temp);
        packetMap.get(trueProtocal).add(new myPacket(num.getNum(), p));

    }

    public void printStringArray(String[] tar) {
        for (String s : tar) {
            System.out.print(s + " ");
        }
        System.out.println();
    }

}
